package core.codeGeneration;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class CodeGenerator {

	public enum Stack {PcO, PcL, TabLabel}
	
	private LebalTable tabLabel;
	
	private LabelControlStack labelStack;
	
	private OperandControlStack operandStack;
	
	private int proxTemp;
	
	private int proxLabelTemp;
	
	private int lineCount;
	
	private FileWriter fileWriter;
	
	private BufferedWriter bufWriter;
	
	private FileWriter tabLabelFileWriter;
	
	private BufferedWriter tabLabelBufWriter;
	
	private static CodeGenerator instance;
	
	private CodeGenerator(){
		
	}
	
	public static CodeGenerator getInstace(){
		if(instance == null){
			return instance = new CodeGenerator();
		}
		return instance;
	}
	
	public void closeStream(){
		try {
			tabLabelBufWriter.close();
			bufWriter.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void emit(String... strings){
//		System.out.println("emit: " + strings);
	
		StringBuffer result = new StringBuffer("[");
		for (String string : strings) {
			result.append(" " + string);
		}
		
		result.append(" ]");
		
		try {
			lineCount++;
			bufWriter.write(lineCount + ".	" + result.toString());
			bufWriter.newLine();
			bufWriter.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void insert(String label, int value){
		tabLabel.insert(label, value);
		
		try {
			tabLabelBufWriter.newLine();
			tabLabelBufWriter.write(label + "	" + value);
			tabLabelBufWriter.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public String pop(Stack stack){
		if(stack.equals(Stack.PcO)){
			return operandStack.pop();
		}
		return labelStack.pop();
	}

	
	public void push(Stack stack, String value) {
		switch (stack) {
			case PcL:
				labelStack.push(value);
				
				break;
			case PcO:
				operandStack.push(value);
				
				break;
		}
	}
	
	public String makeTemp(){
		proxTemp++;
		return "T" + proxTemp;
	}
	
	public void resetTemp(){
		proxTemp = 0;
	}
	
	public String makeLabel(){
		proxLabelTemp++;
		return "L" + proxLabelTemp;
	}

	public static void main(String[] args) {
		CodeGenerator g = new CodeGenerator();
	}
	public void initializeAtributionCode(String leftSize) {
		resetTemp();
	}

	public int getNextCommandLine() {
		return lineCount + 1;
	}

	public void init(String fileName) {
		proxTemp = 0;
		proxLabelTemp = 0;
		lineCount = 0;
		labelStack = new LabelControlStack();
		operandStack = new OperandControlStack();
		tabLabel = new LebalTable();
		
		File intCodeFile = new File("codeFiles\\" + fileName + " Intermediary Code.txt");
		try {
			fileWriter = new FileWriter(intCodeFile);
			bufWriter = new BufferedWriter(fileWriter);
			
		} catch (IOException e) {
		}
		
		//Arquivo no qual ser� escrita a LabelTable
		
		File tabLabelFile = new File("codeFiles\\" + fileName + " Tab Label.txt");
		try {
			tabLabelFileWriter = new FileWriter(tabLabelFile);
			tabLabelBufWriter = new BufferedWriter(tabLabelFileWriter);
			tabLabelBufWriter.write("Label	Value");
			
		} catch (IOException e) {
		}
	}
}
